﻿/*
 * Copyright (C) 2009-2010 Valerio Fuoglio <valerio.fuoglio@gmail.com>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using Lastfm;
using Lastfm.Scrobbling;

namespace LightScrobbler
{
    internal partial class MainDialog : Form
    {
        private readonly DriveDetector _driveDetector;
        private readonly List<RadioButton> _selectSrcGroup;
        private List<Entry> _playedTracks;
        private List<Entry> _skippedTracks;

        public MainDialog()
        {
            InitializeComponent();           

            EnableControls(true);
            _selectFileButton.MaximumSize = new Size(20, 20);
            _selectFileButton.MinimumSize = new Size(20, 20);
            MinimumSize = new Size(300, 240);
            Text = "LightScrobbler" + " - " + 
                Assembly.GetExecutingAssembly().GetName().Version;
            ActiveControl = _usernameTextBox;
            MinimumSize = Size;

            _selectSrcGroup = new List<RadioButton> {_fileRadio, _driveRadio};

            foreach (DriveInfo drvInfo in DriveInfo.GetDrives())
            {
                // Load only removable devices
                if (drvInfo.DriveType != DriveType.Removable ||
                    drvInfo.IsReady == false) continue;

                try
                {
                    if (drvInfo.VolumeLabel != null)
                        _driveCombo.Items.Add(drvInfo.Name + " (" + drvInfo.VolumeLabel + ")");
                }
                catch(IOException)
                {
                    _driveCombo.Items.Add(drvInfo.Name);
                }
            }

            _driveCombo.Sorted = true;
            _driveCombo.DropDownStyle = ComboBoxStyle.DropDownList;


            if (_driveCombo.Items.Count == 0)
            {
                _driveRadio.Enabled = false;
                _driveRadio.Checked = false;
                _fileRadio.Checked = true;
            }
            else
            {
                _driveCombo.SelectedIndex = 0;
            }

            foreach (RadioButton radio in _selectSrcGroup)
                radio.CheckedChanged += _on_radioChecked_changed;

            _fileRadio.Checked = true;
            ManageSrcRadio(_fileRadio);

            _driveDetector = new DriveDetector();
            _driveDetector.DeviceArrived += OnDriveArrived;
            _driveDetector.QueryRemove += OnQueryRemove;
            _driveDetector.DeviceRemoved += OnDriveRemoved;

            Shown += AfterShown;
        }

        public override sealed string Text
        {
            get { return base.Text; }
            set { base.Text = value; }
        }

        public override sealed Size MinimumSize
        {
            get { return base.MinimumSize; }
            set { base.MinimumSize = value; }
        }

        private void ManageSrcRadio(RadioButton active)
        {
            if (active == _fileRadio)
            {
                _driveRadio.Checked = false;
                _driveCombo.Enabled = false;
                _driveLabel.Enabled = false;

                _dataLabel.Enabled = true;
                _selectFileButton.Enabled = true;
                _dataLabel.Enabled = true;
                _selectFileTextBox.Enabled = true;
                return;
            }

            if (active == _driveRadio)
            {
                _fileRadio.Checked = false;
                _dataLabel.Enabled = false;
                _selectFileButton.Enabled = false;
                _dataLabel.Enabled = false;
                _selectFileTextBox.Enabled = false;

                _driveRadio.Checked = true;
                _driveCombo.Enabled = true;
                _driveLabel.Enabled = true;
            }
        }

        private void _on_radioChecked_changed(object sender, EventArgs e)
        {
            // Managing only if checked
            if (!((RadioButton) sender).Checked)
                return;

            ManageSrcRadio((RadioButton) sender);
        }

        // Procedure to execute after form has been shown
        private void AfterShown(object sender, EventArgs e)
        {
            // Ask user wants to use an autodetected scrobbler log
            if (File.Exists(Application.StartupPath + "\\.scrobbler.log"))
            {
                DialogResult result = MessageBox.Show(
                    "A scrobbler log has been found in LightScrobbler's execution folder.\n\nWould you scrobble it?",
                    "Scrobbler log found", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                    MessageBoxDefaultButton.Button1);
                if (result == DialogResult.Yes)
                {
                    _selectFileTextBox.Text = Application.StartupPath + "\\.scrobbler.log";
                }
                return;
            }


            // Search for scrobbler file into removable drives

            DriveInfo[] logicalDrives = DriveInfo.GetDrives();

            foreach (DriveInfo drvInfo in logicalDrives)
            {
                // We're searching ONLY for removable devices
                if (drvInfo.DriveType != DriveType.Removable) continue;

                string logPath = drvInfo.RootDirectory.Name + ".scrobbler.log";

                try
                {
                    if (File.Exists(logPath))
                    {
                        using (var fs = new FileStream(logPath, FileMode.Open, FileAccess.Read))
                        {
                            DialogResult result = MessageBox.Show(
                                "A scrobbler log has been found: " + logPath + "\n\nWould you scrobble it?",
                                "Scrobbler log found", MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                                MessageBoxDefaultButton.Button1);
                            if (result == DialogResult.Yes)
                            {
                                _selectFileTextBox.Text = logPath;
                            }
                            return;
                        }
                    }
                }
                catch (Exception)
                {
                    // Not handling any exception, just "next"
                    continue;
                }
            }
        }

        private void UpdateStatusText(string message)
        {
            _statusBarTextBox.Text = message;
        }

        private void EnableControls(bool enable)
        {
            _usernameTextBox.Enabled = enable;
            _passwordTextBox.Enabled = enable;
            _selectFileTextBox.Enabled = enable;
            _selectFileButton.Enabled = enable;
            _readLogButton.Enabled = enable;
            _aboutButton.Enabled = enable;
            _exitButton.Enabled = enable;
        }

        private void SelectFileButtonClick(object sender, EventArgs e)
        {
            var ofn = new OpenFileDialog();
            ofn.Filter = "All Files (*.*)|*.*";
            ofn.Title = "Type File";
            ofn.Multiselect = false;
            ofn.CheckFileExists = true;
            ofn.CheckPathExists = true;

            DialogResult result;

            if ((result = ofn.ShowDialog()) == DialogResult.Cancel)
                return;

            if (result == DialogResult.OK)
            {
                _selectFileTextBox.Text = ofn.FileName;
                return;
            }
        }

        private void Send_Click(object sender, EventArgs e)
        {
            if (!CheckFields()) return;

            ScrobbleSessionData.Reset();
            ScrobbleSessionData ssd = ScrobbleSessionData.GetInstance();
            ssd.Username = _usernameTextBox.Text;
            ssd.Password = Utilities.md5(_passwordTextBox.Text);

            if (_fileRadio.Checked)
                ssd.FilePath = _selectFileTextBox.Text;
            else
            {
                string path = _driveCombo.SelectedItem.ToString()[0] + ":\\.scrobbler.log";
                if (!File.Exists(path))
                {
                    MessageBox.Show(path + " doesn't exist.\n\nPlease select another file.", "File not found",
                                    MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return;
                }

                ssd.FilePath = path;
            }

            _readLogButton.Enabled = false;
            _thread = new Thread(ReadLog);
            _thread.Start();
        }


        private bool CheckFields()
        {
            if (_usernameTextBox.Text == "")
            {
                MessageBox.Show("Please insert your username", "No username", MessageBoxButtons.OK,
                                MessageBoxIcon.Warning);
                return false;
            }

            if (_passwordTextBox.Text == "")
            {
                MessageBox.Show("Please insert your password", "No password", MessageBoxButtons.OK,
                                MessageBoxIcon.Warning);
                return false;
            }

            if (_fileRadio.Checked && _selectFileTextBox.Text == "")
            {
                MessageBox.Show("Please select your file to send", "No file selected", MessageBoxButtons.OK,
                                MessageBoxIcon.Warning);
                return false;
            }

            if (_driveCombo.SelectedItem != null)
            {
                string selDriveLog = new string(((string) _driveCombo.SelectedItem)[0], 1) + ":\\.scrobbler.log";

                if (_driveRadio.Checked && !File.Exists(selDriveLog))
                {
                    MessageBox.Show(
                        "Cannot find scrobbler's log into selected drive.\n\n" + selDriveLog + " NOT FOUND.",
                        "Selected file not found", MessageBoxButtons.OK, MessageBoxIcon.Stop);
                    return false;
                }
            }

            return true;
        }

        private void MainDialog_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (_thread != null) _thread.Abort();
        }

        private void _aboutButton_Click(object sender, EventArgs e)
        {
            new About().Show();
        }

        private void _exitButton_Click(object sender, EventArgs e)
        {
            Close();
        }

        #region Nested type: EnableControlsCallback

        internal delegate void EnableControlsCallback(bool enable);

        #endregion

        #region Nested type: UpdateTextCallback

        internal delegate void UpdateTextCallback(string message);

        #endregion
    }
}